import { _ } from "core-js";

//封装动画函数
function animation(duration, from, to, onProgress) {
  const dis = to - from
  const speed = dis / duration
  const startTime = Date.now()
  let value = from
  onProgress(value)

  function _run() {
    const now = Date.now()
    const time = now - startTime
    if (time >= duration) {
        value = to
        onProgress(value)
        return
    }
    const d = time * speed
    value = from + d
    onProgress(value)
    requestAnimationFrame(_run)
  }
  requestAnimationFrame(_run)
}

//并发队列
function paralleTask(tasks, paralleCount = 2) {
  return new Promise((resolve) => {
      if (tasks.length === 0) {
        resolve()
        return
      }
      let nextIndex = 0
      let finishCount = 0
      function _run() {
        //运行下一个任务
        const task = tasks[nextIndex]
        nextIndex++
        task().then(() => {
            finishCount++
            if (nextIndex <tasks.length) {
                _run()
            } else if (finishCount === tasks.length) {
                resolve()
            }
        })
      }
      for (let i = 0; i < paralleCount && i <= tasks.length; i++) {
          _run()
      }
  })
}

//惰性函数
function createCopyText() {
  if (navigator.clipboard) {
    return (text) => {
      navigator.clipboard.writeText(text)
    }
  } else {
      return (text) => {
          const input = document.createElement('input')
          input.setAttribute('value', text)
          document.body.appendChild(input)
          input.select()
          document.execCommand('copy')
          document.body.removeChild(input)
      }
  }
}

const copyText = createCopyText()

//统计函数  array.filter(fn).lengthn
function countBy(array, generateKey) {
    const result = {}
    for (const u of array) {
        const key = generateKey(u)
        if (result[key]) {
            result[key]++
        } else {
            result[key] = 1
        }
    }
    return result
}

//数据分组
function groupBy(arr, generateKey) {
    if (typeof generateKey === 'string') {
        const propName = generateKey
        generateKey = (item) => item[propName]
  }
  const result = {}
  for (const item of arr) {
      const key = generateKey(item)
      if (!result[key]) {
          result[key] = []
      }
      result[key].push(item)
  }
  return result
}

//封装分时函数
const chunkSplitor = (task) => {
    setTimeout(() => {
        task((time) => time < 16)
    }, 30)
}

function performChunk(datas, consumer, chunkSplitor) {
    if (typeof datas === 'number') {
        datas = new Array(datas)
    }
    if (datas.length === 0) {
        return
    }
    if (!chunkSplitor && globalThis.requestIdleCallback) {
        chunkSplitor = (task) => {
            requestIdleCallback((idle) => {
                task(() => idle.timeRemaining())
            })
        }
    }
    let i = 0  //目前应该取出的任务下标
    //执行一块任务
    function _run() {
        if (i === datas.length) {
            return
        }
        chunkSplitor((hasTime) => {
            const now = Date.now()
            while (hasTime(Date.now() - now) && i < datas.length) {
                //在这一帧还有空闲时间
                const item = datas[i]
                consumer(item, i)
                i++
            }
            _run()
        })
    }
    _run()
}

//函数防抖
function debounce(func, duration = 500) {
    let timerId
    return function(...args) {
      clearTimeout(timerId)
      timerId = setTimeout(() => {
        func.apply(this, args)
      },duration)
    }
}

//函数节流
function throttle(callback, time, immediately = true) {
    if (immediately) {
        let t
        return function() {
            if (!t || Date.now() - t >= time) {
                callback.apply(null, arguments)
                t = Date.now
            }
        }
    } else {
        let timer
        return function(...args) {
            if (timer) return
            timer = setTimeout(() => {
                callback.apply(this, args)
                timer = null
            }, time)
        }
    }
}

//柯里化函数
function curry(func) {
    //得到从下标1开始的参数
    let args = Array.prototype.slice.call(arguments, 1)
    let that = this
    return function() {
        let curArgs = Array.from(arguments) //当前调用的参数
        let totalArgs = args.concat(curArgs)
        if (totalArgs.length >= func.length) {
            //参数数量够
            return func.apply(null, totalArgs)
        } else {
            //参数数量不够
            totalArgs.unshift(func)
            return that.curry.apply(that, totalArgs)
        }
    }
}

//深度克隆
function deepclone(value) {
    const cache = new WeakMap()
    function _deepclone(value) {
        if (value === null || typeof value !== 'object') {
            return value
        }
        if (cache.has(value)) {
            return cache.get(value)
        }
        const result = Array.isArray(value) ? [] : {}
        Object.setPrototypeOf(result, Object.getPrototypeOf(value))
        cache.set(value, result)
        for (const key in value) {
            if (value.hasOwnProperty(key)) {
                result[key] = _deepclone(value[key])
            }
        }
        return result
    }
    return _deepclone(value)
}